perm filename SUPSER.MID[NET,MRC]1 blob
sn#336692 filedate 1978-02-22 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00017 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00003 00002 TITLE SUPSER
C00005 00003 ITS TTY definitions
C00009 00004 ITS output buffer codes
C00011 00005 Data area
C00014 00006 Interrupt server
C00016 00007 Start of program
C00018 00008 Log this connection
C00020 00009 Paw over user console characteristics
C00022 00010 Final initialization
C00024 00011 Network input interrupt
C00026 00012 Send character to the PTY
C00029 00013 PTY input interrupt
C00032 00014 Datamedia conversion subroutines
C00035 00015 Datamedia command table
C00038 00016 More DM command frobs
C00041 00017 Subroutines
C00044 ENDMK
C⊗;
TITLE SUPSER
SUBTTL Definitions
; Mark Crispin, SU-AI, February 1978
; Assembly switches
IFNDEF SVRSKT,SVRSKT==137 ; default listen socket
IFNDEF LOKTMO,LOKTMO==5 ; # of 15-second frobs of lock timeout
IFNDEF PDLLEN,PDLLEN==50 ; stack length
IFNDEF VSZMAX,VSZMAX==50. ; maximum TCMXV
; AC definitions. 0→3 are used by NETWRK
X=4 ? Y=5 ? Z=6 ? A=7 ? B=10 ? C=11 ? P=17
; SAIL system bit definitions
INTPTO==001000,, ; PTY interrupt
INTCLK==000200,, ; clock interrupt
DMLIN== 040000,, ; Datamedia
IMPBIT==001000,, ; IMP TTY
FCS== 000020,, ; full character set mode
FULTWX==000004,, ; no echo
TLKRNG==000001,, ; TALKing
SUBTTL ITS TTY definitions
; These definitions are the various bits, words, etc. for the ITS terminal
; service system calls and are here for convenience and clarity. This is
; abridged from [MIT-AI] SYSTEM;BITS >, the monitor bits definition file.
; TTYOPT variable (terminal capabilities)
%TOALT==200000,, ; 1 → standardise altmodes
%TOCLC==100000,, ; 1 → convert cases on input
%TOERS==040000,, ; 1 → this terminal can erase
%TOHDX==020000,, ; 1 → half duplex
%TOMVB==010000,, ; 1 → can backspace
%TOSAI==004000,, ; 1 → has SAIL graphics
%TOSA1==002000,, ; 1 → init %TSSAI in new jobs (use graphics)
%TOOVR==001000,, ; 1 → can overprint
%TOMVU==000400,, ; 1 → can line starve (ie a display)
%TOMOR==000200,, ; 1 → do **More** processing (init %TSMOR)
%TOROL==000100,, ; 1 → scroll (init %TSROL for new jobs)
%TORAW==000040,, ; 1 → no cursor motion optimization
%TOLWR==000020,, ; 1 → lower case keyboard
%TOFCI==000010,, ; 1 → has bucky bit keyboard
%TOIML==000004,, ; 1 → acts like a grIMLAC (funny ↑PF, ↑PB)
%TOLID==000002,, ; 1 → can insert/delete lines
%TOCID==000001,, ; 1 → can insert/delete characters
%TPPLF==700000 ; LF padding
%TPPCR==070000 ; CR padding
%TPPTB==007000 ; TAB padding (0 → no tabs, 1 → tabs)
%TPTEL==000100 ; 1 → CR → CRLF for ARPAnet protocol
%TPCBS==000040 ; 1 → intelligent terminal protocol (↑\)
%TP11T==000020 ; 1 → PDP-11 TV (reflects %TY11T)
%TPORS==000010 ; 1 → output reset should do something
%TPIBC==000002 ; 1 → correspondence code 2741
%TPIBM==000001 ; 1 → IBM 2741
; TCTYP variable (terminal type)
%TNPRT==0 ; printing console, glass TTY, etc.
%TNDP==1 ; good Datapoint
%TNODP==2 ; inferior losing Datapoint
%TNIML==3 ; grIMLAC
%TNTEK==4 ; Tektronix 4000 series
%TNTV==5 ; PDP-11 TV
%TNMEM==6 ; Memowreck
%TNSFW==7 ; Software
%TNTRM==10 ; Terminet
%TNESC==11 ; ASCII standard display (VT52, etc.)
%TNDTM==12 ; Datamedia 2500
%TNMAX==13 ; 1 + largest terminal type
; Components of an input character in 12-bit mode.
%TXASC==0177 ; ASCII part
%TXCTL==0200 ; control
%TXMTA==0400 ; meta
%TXSFT==1000 ; shift
%TXSFL==2000 ; shift lock
%TXTOP==4000 ; top
subttl ITS output buffer codes
; These are the ITS output buffer codes (used by Software terminals).
%TDMOV==200 ; move cursor OV OH NV NH
%TDMV1==201 ; move cursor; NV NH
%TDEOF==202 ; clear to end of screen
%TDEOL==203 ; clear to end of line
%TDDLF==204 ; delete character after cursor
%TDMTF==205 ; motor off
%TDMTN==206 ; motor on
%TDCRL==207 ; terpri
%TDNOP==210 ; no-op
%TDBS==211 ; backspace
%TDLF==212 ; line feed
%TDRCR==213 ; carriage return
%TDORS==214 ; output reset
%TDQOT==215 ; quote next character (mystery command)
%TDFS==216 ; cursor forward
%TDMV0==217 ; move cursor NV NH
%TDCLR==220 ; clear screen
%TDBEL==221 ; feep!
%TDINI==222 ; reset reset reset
%TDILP==223 ; insert line; count
%TDDLP==224 ; delete line; count
%TDICP==225 ; insert character; count
%TDDCP==226 ; delete character; count
%TDBOW==227 ; inverse video
%TDRST==230 ; reset inverse video, etc.
%TDMAX==231 ; 1 + largest display code
SUBTTL Data area
; TTYSET command words
TYSBLK==.
SETVSZ: 016400,,0 ; set screen height
GAGOFF: 024400,,0 ; gag off
MODSET: 014400,,0 ; set DM mode
NTYSTS==.-TYSBLK
; Terminal location string
TERMID: 'TERMID
CORBEG==. ; start of initialized core storage
TERSTR: BLOCK 10. ; console location string
; Terminal characteristics
CNSBLK: BLOCK 1 ; CNSGET info
TCTYP: BLOCK 1 ; TCTYP for server
TTYOPT: BLOCK 1 ; TTYOPT for server
TCMXV: BLOCK 1 ; TTY page length
TCMXH: BLOCK 1 ; TTY width
TTYROL: BLOCK 1 ; TTYROL variable
CNSBLL==.-CNSBLK
; Datamedia translator variables
HPOS: BLOCK 1 ; horizontal position
VPOS: BLOCK 1 ; vertical position
SCRMST: BLOCK 3*<VSZMAX+1> ; screen character allocation table
GETCXP: BLOCK 1 ; -1 → get cursor X position
GETCYP: BLOCK 1 ; -1 → get cursor Y position
INDLMP: BLOCK 1 ; -1 → in I/D mode
LFFLSP: BLOCK 1 ; -1 → flush a line feed
QUOTEP: BLOCK 1 ; -1 → quote next character
128CHP: BLOCK 1 ; -1 → FCS terminal
OVRPRP: BLOCK 1 ; -1 → TV terminal
; Interrupt flags
PTINTP: BLOCK 1 ; -1 → PTI interrupt
NTINTP: BLOCK 1 ; -1 → NTI interrupt
; Protocol flags
PRESCP: BLOCK 1 ; -1 → protocol escape seen
SDCMDP: BLOCK 1 ; -1 → in SUPDUP protocol command
EATERP: BLOCK 1 ; -1 → getting terminal string
NODETP: BLOCK 1 ; -1 → don't detach this guy
BKYBTS: BLOCK 1 ; -1 → incoming bucky bits
; Other storage
TERMBP: BLOCK 1 ; terminal byte pointer
TTYLIN: BLOCK 1 ; line number of PTY
IDLTIM: BLOCK 1 ; idle time in 15-second units
PDL: BLOCK PDLLEN ; stack
COREND==.-1 ; end of initialized storage
SUBTTL Interrupt server
; Interrupts only set flags which the main program (normally in INTW⊗
; state) looks at.
INTSER: SKIPN X,JOBCNI ; get interrupt status
JRST 4,.-1
TLNE X,(INTPTO) ; PTY int
SETOM PTINTP
TLNE X,(INTCLK) ; CLK int
JRST CLKSER
TLNE X,(INTINP) ; NTI int
SETOM NTINTP
TLNE X,(INTIMS) ; status change
JRST INTDIE
TLNE X,(INTINR)
OUTSTR [ASCIZ/*INR*
/]
TLNE X,(INTINS) ; IMP INS int
OUTSTR [ASCIZ/*INS*
/]
DISMIS
; Service clock interrupt
CLKSER: AOSE IDLTIM ; bump idle time
JRST CLKSR1
UNLOCK ; idle timeout; unlock
MOVE TTYLIN
TTYJOB
PTGETL
TLNE 1,(TLKRNG) ; TALKing?
JRST CLKSR1 ; don't kill him if so!
JUMPN CLKSR1
SETOM NODETP ; forget about detaching
JRST INTDIE ; idle and not logged in--bye bye!
CLKSR1: MOVEI 2 ; check connection status
MTAPE NET,
TLNN 1,(CLSS\CLSR) ; send side gronked?
TLNE 2,(CLSS\CLSR) ; receive side?
JRST INTDIE
DISMIS
SUBTTL Start of program
SUPSER: JFCL
RESET
MOVE ['SUPSER]
SETNAM
SETZM CORBEG
MOVE [CORBEG,,CORBEG+1]
BLT COREND
MOVE P,[PDL(-PDLLEN)]
MOVEI [DEBREAK ? EXIT]
MOVEM JOBAPR
CLKINT 5.*60.*60. ; must die if around too long
OUTSTR [ASCIZ/SUPSER started
/]
; Listen for a connection on our socket
SETOM NODETP ; don't try to detach
MOVEI SVRSKT
MOVEM LSNSKT
PUSHJ P,LISTEN
; Set up interrupts
MOVEI INTSER
MOVEM JOBAPR ; set up server location
CLKINT 60.*15. ; start slow ticking clock
MOVSI (INTPTO\INTCLK\INTINR\INTINS\INTIMS\INTINP)
INTENB ; turn on interrupts
; Set up terminal id for interested spies
MOVEI TERMID
MOVEM JOBVER
SUBTTL Log this connection
OUTSTR [ASCIZ/Connected to /]
PUSHJ P,MAPHST ; map in host table
MOVE HOST
PUSHJ P,HSTNUM ; get HDB
JFCL ; sorry about errors
MOVEI Y,(1) ; host name
HRLI Y,440700
SKIPA X,[440700,,TERSTR]
CPYHST: IDPB Z,X
ILDB Z,Y
JUMPN Z,CPYHST
HLRZ Y,1 ; pointer to system name
MOVE Z,(Y) ; get system name
MOVE Y,FSOCKT ; and ICP socket
CAMN Z,[ASCII/TIP/] ; on a TIP? (with SUPDUP???)
TRNE Y,177774 ; just paranoia; make sure a TIP port
JRST NOTTIP
MOVEI Z,"#
IDPB Z,X
LSH Y,-16.
IDIVI Y,8. ; ports are octal
JUMPE Y,1DIGTP
ADDI Y,"0 ? IDPB Y,X
1DIGTP: ADDI Z,"0 ? IDPB Z,X
NOTTIP: MOVEM X,TERMBP
PUSHJ P,SETANM ; set our alias name
PUSHJ P,UNMHST ; map out the host table
OUTSTR TERSTR
OUTSTR [ASCIZ/
/]
SUBTTL Paw over user console characteristics
; Get terminal characteristics
MOVE Y,[440600,,CNSBLK] ; pointer to characteristics block
MOVEI Z,6
GETSIZ: PUSHJ P,NETICW
IDPB Y
SOJG Z,GETSIZ
HLRO X,CNSBLK
MOVNS Z,X ; size of block
CAILE Z,CNSBLL-1
MOVEI Z,CNSBLL-1 ; additional args we don't know about
IMULI Z,6
GETCNS: PUSHJ P,NETICW
IDPB Y
SOJG Z,GETCNS
CAIN X,CNSBLL-1
JRST CHKTRM
CAIG X,CNSBLL ; more than we wanted?
JRST [ OUTSTR [ASCIZ/User sent too few args!
/]
JRST CHKTRM]
OUTSTR [ASCIZ/User sent too many args!
/]
SUBI X,CNSBLL-1
IMULI X,6
PUSHJ P,NETICW ; eat extra bytes
SOJG X,.-1
; Check terminal out
CHKTRM: MOVE TCTYP
CAIE %TNSFW ; software?
JRST [ MOVEI X,[ASCIZ/Invalid TCTYP setting!
/]
OUTSTR (X)
PUSHJ P,SNDMSG
JRST SUICID]
MOVE TTYOPT
TLNE (%TOOVR)
SETOM OVRPRP ; remember overprinting!
TLNN (%TOSAI) ; FCS terminal?
JRST NOTSAI
MOVEI X,1
IORM X,MODSET ; set DM128 bit
SETOM 128CHP
NOTSAI: AND [%TOERS\%TOMVB\%TOMVU\%TOFCI\%TOLID\%TOCID\%TPCBS]
CAMN [%TOERS\%TOMVB\%TOMVU\%TOFCI\%TOLID\%TOCID\%TPCBS]
JRST GREET
MOVEI X,[ASCIZ/Insufficient terminal capabilities!
/]
OUTSTR (X)
PUSHJ P,SNDMSG
JRST SUICID
SUBTTL Final initialization
; Greet the user
GREET: MOVEI X,[ASCIZ/SU A.I. Lab KL-10
/]
PUSHJ P,SNDMSG
; Get a PTY, put its number in A and other places
PTYGET A
JRST [ MOVEI X,[ASCIZ/All network ports in use.
/]
PUSHJ P,SNDMSG
PUSHJ P,CLOSER
JRST SUICID]
HRRZM A,TTYLIN ; dumb interrupts
MOVSI (A)
IORM GAGOFF
IORM SETVSZ
IORM MODSET
; Initialize the user's display mode
MOVEI %TDNOP
PUSHJ P,NETOCH
MOVEI %TDCLR
PUSHJ P,NETOCH
PUSHJ P,NETSND
; And get the terminal ready
MOVSI B,(DMLIN\IMPBIT\FCS)
PTSETL A ; set initial bits
MOVE TCMXV
CAILE VSZMAX
MOVEI VSZMAX
MOVEM TCMXV
HRRM SETVSZ
MOVE [-NTYSTS,,TYSBLK]
TTYSET ; turn GAG bit off
MOVEI B,↑M
PTWR1W A
MOVNI 1,LOKTMO
MOVEM 1,IDLTIM ; initialize lock timeout
LOCK ; keep response good
SETZM NODETP ; okay to detach jobs now
JRST MAINL0
; Main program loop
MAINL: IWAIT ; wait for an interrupt
MAINL0: AOSG NTINTP ; net input?
JRST NTISER
AOSG PTINTP ; PTY input?
JRST PTISER
JRST MAINL ; back to sleep for us
SUBTTL Network input interrupt
NTISER: PUSHJ P,NETICH ; get character from the network
JRST MAINL0 ; network input buffer empty
SKIPL IDLTIM
LOCK
MOVNI 1,LOKTMO
MOVEM 1,IDLTIM ; reset idle time
SKIPE BKYBTS ; if have bucky bits
JRST PTYSN0 ; forget all this cruft
SKIPE EATERP ; getting terminal name?
JRST [ IDPB TERMBP ; save character
JUMPN NTISER
SETZM EATERP ; got it all
JRST NTISER]
AOSN PRESCP
JRST [ CAIN ↑\ ; quoted?
JRST PTYSN0
TRZN 100 ; bucky bits?
JRST NTISER ; losing somehow
LSH 7
MOVEM BKYBTS
JRST NTISER]
AOSN SDCMDP
JRST [ CAIN 301 ; logout?
SETOM NODETP
CAIN 302 ; get terminal name?
JRST [ SETOM EATERP
MOVEI ":
IDPB TERMBP
MOVEI <" >
IDPB TERMBP
JRST NTISER]
JRST NTISER]
CAIN 300 ; start of protocol command?
JRST [ SETOM SDCMDP
JRST NTISER]
CAIN ↑\ ; protocol escape command?
JRST [ SETOM PRESCP
JRST NTISER]
; Send character to the PTY
PTYSN0: MOVE B,
IOR B,BKYBTS ; add in bucky bits
SETZM BKYBTS
MOVE X,B
TRZ X,%TXMTA\%TXCTL ; get character without CONTROL and META
CAIN X,%TXTOP\"β ; beta?
JRST @FNYQOT
CAIE X,%TXTOP\"≡ ; equivalence?
CAIN X,%TXTOP\"∨ ; or?
FNYQOT: JRST [PUSH P,B
SETZ B, ; quote with escape
PTWR1S A
JFCL
POP P,B
JRST PTYSN1]
CAIN X,%TXTOP\"_ ; underscore?
JRST [ MOVEI X,137
DPB X,[000700,,B]
JRST PTYSN1]
CAIN X,"← ; backarrow?
JRST [ MOVEI X,030
DPB X,[000700,,B]
JRST PTYSN1]
CAIN X,↑Z ; [CALL]?
JRST [ MOVEI X,↑C ; yes, convert to our [CALL]
DPB X,[000700,,B]
JRST PTYSN1]
CAIN X,%TXTOP\"A ; [ESCAPE]?
JRST [ SETZ B,
JRST PTYSND]
CAIN X,%TXTOP\"B ; [BREAK]?
JRST [ PUSH P,["-]
SETZ B,
JRST PTYSN2]
CAIN X,%TXTOP\"C ; [CLEAR]?
JRST [ MOVEI B,↑↑
JRST PTYSND]
PTYSN1: TRZ B,%TXTOP ; flush top now
TRZN B,%TXMTA ; meta set?
JRST PTYSND
PUSH P,B
MOVEI B,200 ; <EDIT>[NULL]
PTYSN2: PTWR1S A ; send prefix meta command
JFCL ; will lose soon enough
POP P,B
PTYSND: PTWR1S A ; send character to PTY
JRST [ MOVEI %TDBEL ; bell
PUSHJ 17,NETOCH
PUSHJ 17,NETSND ; output it
JRST NTISER]
JRST NTISER ; try for more user characters
SUBTTL PTY input interrupt
PTISER: PTRD1S A ; get a character from the PTY
JRST MAINL0 ; PTY input buffer empty
SKIPGE IDLTIM
LOCK
PTISR1: MOVNI 1,LOKTMO
MOVEM 1,IDLTIM ; reset idle time
ANDI B,377 ; flush funny 400 bit
AOSN LFFLSP ; flush a line feed?
CAIE B,↑J
CAIA
JRST DMNOP
AOSN QUOTEP ; quote frob?
JRST DMSND
AOSN GETCXP ; set X position?
CAIG B,<" > ; yes, abort?
JRST CHKCYP
XORI B,140
CAMLE B,TCMXH ; beyond screen limit?
SETZ B,
MOVEM B,HPOS
SETOM GETCYP
JRST DMNOP
CHKCYP: AOSN GETCYP ; set Y position?
CAIG B,<" > ; yes, abort?
JRST CHKDMC
XORI B,140
CAMLE B,TCMXV ; beyond screen limit?
SETZ B,
MOVEM B,VPOS
JRST SETCPS ; finally set position
CHKDMC: CAIG B,<" > ; DM command?
XCT DMCTAB(B)
DMSND: CAIN B,013 ; integral sign?
JRST [ MOVEI B,177
JRST DMSND0]
CAIN B,"_ ; underscore?
JRST [ MOVEI B,137
JRST DMSND0]
SKIPN 128CHP
JRST DMSND0
CAIN B,"↑ ; uparrow?
JRST [ MOVEI B,013
JRST DMSND0]
CAIN B,"← ; backarrow?
JRST [ MOVEI B,030
JRST DMSND0]
CAIN B,177 ; integral sign?
JRST [ MOVEI B,013
JRST DMSND0]
DMSND0: CAIL B,200 ; a %TD code?
JRST NOTPCH
SKIPN OVRPRP
JRST ISPCH
PUSHJ P,GETSMD
TDNN X,(Y)
JRST MRKNBL ; position already blank
MOVEI %TDDLF ; delete character at this position
PUSHJ P,NETOCH
MRKNBL: IORM X,(Y) ; mark position as non-blank
ISPCH: AOS HPOS ; no, account for character
NOTPCH: MOVE B
PUSHJ P,NETOCH
DMNOP: PTRD1S A ; try for more while here
CAIA
JRST PTISR1 ; more coming
PUSHJ P,NETSND ; force buffer out
JRST MAINL0 ; scan the world again
; Datamedia conversion subroutines
SCLEAR: MOVEI %TDCLR ; clear screen
PUSHJ P,NETOCH
SETZM HPOS ; home up
SETZM VPOS
SKIPN OVRPRP
JRST CANCEL
SETZM SCRMST ; clear screen bit mask
MOVE [SCRMST,,SCRMST+1]
BLT SCRMST+3*VSZMAX-1
CANCEL: SETZM INDLMP
JRST DMNOP
CLEOL: MOVEI %TDEOL
PUSHJ P,NETOCH
SKIPN OVRPRP
JRST DMNOP
PUSHJ P,GETSMD
ANDCAM X,(Y) ; flag current position as blank
SUBI X,1
ANDCAM X,(Y) ; flag rest of word as blank
CAIE Z,2
SETZM 1(Y) ; 0 or 1 → flag next word as blank
JUMPN Z,DMNOP
SETZM 2(Y) ; 0 → flag word after that as blank
JRST DMNOP
SETCPS: MOVEI %TDMV0 ; set cursor position
PUSHJ P,NETOCH
MOVE VPOS
PUSHJ P,NETOCH
MOVE HPOS
PUSHJ P,NETOCH
JRST DMNOP
INSLIN: MOVEI %TDILP
SKIPN OVRPRP
JRST IDCMND
MOVEI X,VSZMAX-1
SUB X,VPOS ; # of lines to move
IMULI X,3
ADDI X,377777 ; # of lines-1 w/ sign bit
HRL X,X
HRRI X,SCRMST+3*<VSZMAX-1>-1 ; source address
POP X,3(X) ; reverse BLT
JUMPL X,.-1
IDCMND: PUSHJ P,NETOCH ; insert/delete mode command
MOVEI 1
PUSHJ P,NETOCH
JRST DMNOP
SPACE: MOVEI %TDDLF
PUSHJ P,NETOCH
SKIPN OVRPRP
JRST FORSPC
PUSHJ P,GETSMD
ANDCAM X,(Y) ; flag position as blank
FORSPC: MOVEI %TDFS ; forespace
PUSHJ P,NETOCH
AOS HPOS
JRST DMNOP
SUBTTL Datamedia command table
DMCTAB: JRST DMNOP ; ↑@ no-op
JRST DMNOP ; ↑A no-op
JRST [ SETZM HPOS ; ↑B home up
SETZM VPOS
JRST SETCPS]
JRST DMNOP ; ↑C no-op
JRST DMNOP ; ↑D no-op
JRST DMNOP ; ↑E no-op
JRST DMNOP ; ↑F no-op
MOVEI B,%TDBEL ; ↑G bell
JRST [ SKIPE INDLMP ; ↑H backspace/delete character
JRST [ MOVEI %TDDCP
SKIPN OVRPRP
JRST IDCMND
PUSHJ P,GETSMD
MOVE B,(Y)
LSH X,1
SUBI X,1 ; mask for bits being hacked
ANDCAM X,(Y)
LSH B,1 ; shift characters over
AND B,X
IORM B,(Y)
CAIN Z,2
JRST IDCMND
MOVEI C,1 ; bit to bring in previous words if needed
MOVE B,1(Y)
LSH B,1 ; shift characters over
TLZE B,(1←32.)
IORM C,(Y) ; bring in overflow to next word
MOVEM B,1(Y)
JUMPN Z,IDCMND ; if last word flush
MOVE B,2(Y)
LSH B,1
TLZE B,(1←32.)
IORM C,1(Y)
MOVEM B,2(Y)
JRST IDCMND]
SOSGE HPOS
SETZM HPOS
JRST SETCPS]
JRST [ MOVE HPOS ; ↑I tab
TRZ 7
ADDI 8.
MOVEM HPOS
JRST SETCPS]
JRST [ SKIPE INDLMP ; ↑J line feed/insert line
JRST INSLIN
AOS VPOS
JRST SETCPS]
JRST DMNOP ; ↑K tab clear (no-op)
JRST [ SETOM GETCXP ; ↑L cursor position
JRST DMNOP]
JRST [ AOS X,VPOS ; ↑M terpri
SETZM HPOS
SETOM LFFLSP
MOVEI %TDCRL
PUSHJ P,NETOCH
CAMGE X,TCMXV
JRST DMNOP
MOVE TCMXV ; somehow we scrolled
SOS
MOVEM VPOS
MOVE [SCRMST+3,,SCRMST]
BLT SCRMST+3*VSZMAX-1
JRST DMNOP]
JRST DMNOP ; ↑N blink on (no-op)
JRST DMNOP ; ↑O bold on (no-op)
JRST [ SETOM INDLMP ; ↑P enter I/D mode
JRST DMNOP]
; More DM command frobs
JRST DMNOP ; ↑Q transmit page to computer (no-op)
JRST DMNOP ; ↑R transmit page to printer (no-op)
JRST DMNOP ; ↑S transmit line to computer (no-op)
JRST DMNOP ; ↑T no-op
JRST DMNOP ; ↑U no-op
JRST DMNOP ; ↑V no-op
JRST CLEOL ; ↑W erase to end of line
JRST CANCEL ; ↑X cancel bold, I/D, roll
JRST DMNOP ; ↑Y set tab (no-op)
JRST [ SKIPE INDLMP ; ↑Z line starve/delete row
JRST [ MOVEI %TDDLP
SKIPN OVRPRP
JRST IDCMND
MOVE X,VPOS
LSH X,1
ADD X,VPOS
ADDI X,SCRMST
HRLI X,3(X)
BLT X,SCRMST+3*VSZMAX-1
JRST IDCMND]
SOSGE VPOS
SETZM VPOS
JRST SETCPS]
JRST [ SETOM QUOTEP ; ↑[ quote FCS character
JRST DMNOP]
JRST [ SKIPN INDLMP ; ↑\ forespace/insert character
JRST FORSPC
MOVEI %TDICP
SKIPN OVRPRP
JRST IDCMND
PUSHJ P,GETSMD
MOVE B,(Y)
LSH X,1
SUBI X,1 ; fill in mask to the right
ANDCAM X,(Y)
AND B,X
LSHC B,-1
IORM B,(Y)
CAIN Z,2
JRST IDCMND
MOVE B,1(Y)
SKIPGE C
TLO B,(1←31.) ; bring in bit from previous word
LSHC B,-1
MOVEM B,1(Y)
JUMPN Z,IDCMND
MOVE B,2(Y)
SKIPGE C
TLO B,(1←31.)
LSH B,-1
TRZ B,100000 ; flush overflow bit
MOVEM B,2(Y)
JRST IDCMND]
JRST DMNOP ; ↑] roll on
JRST SCLEAR ; ↑↑ master clear
JRST SCLEAR ; ↑← erase screen
JRST SPACE ; sp delete character and forespace
IFN .-DMCTAB-1-" ,.ERR DMCTAB loses!
SUBTTL Subroutines
; Get screen mask data in Y, Z, X
GETSMD: MOVE Y,VPOS
LSH Y,1
ADD Y,VPOS
MOVE Z,HPOS
LSH Z,-5 ; Z ← word index in line (for cleol)
ADDI Y,SCRMST(Z) ; Y ← addr of screen mask word
MOVE X,HPOS
ANDI X,37
MOVE X,BITTAB(X) ; X ← mask for this byte
POPJ P,
; Bit table
BITTAB: REPEAT 32.,1←<31.-.RPCNT> ; bit table
; Send a message, b.p. in X
SNDMSG: TLOA X,440700 ; set up b.p.
MSGLUP: PUSHJ P,NETOCH
ILDB X
JUMPN MSGLUP ; continue until a null hit
JRST NETSND
; Here to suicide on network errors or idle timeout
INTDIE: INTMSK [0] ; no more interrupts
DEBREAK ; out of interrupt level
SUICID: OUTSTR [ASCIZ/Connection closed.
/]
SKIPE NODETP
JRST DIEDIE ; logout the guy
MOVE A,TTYLIN
TTYJOB A,
JUMPE A,DIEDIE
MOVE A,TTYLIN
MOVEI B,7
PTJOBX A ; clear PTY's input buffer
PTRD1S A ; slurp up stuff in buffer
CAIA
JRST .-2
MOVEI B,[.BYTE 9 ? 600 ? 600 ? "D ? "E ? "T ? "A ? "C ? "H ? ↑M ? ↑J ? 0]
PTWRS9 A
MOVEI 5.
SLEEP ; give it time to happen
PTRD1S A ; slurp up what's left in the buffer
JRST DIEDIE
JRST .-2
DIEDIE: RESET ? EXIT
...LIT: CONSTANTS
; Wonderful network routines
SVRRTS==-1 ; include server routines
ERRTNS==-1 ; include error routines
ERRHAN==-1 ; include automagic error handling
ERRINS==<JRST SUICID> ; error instruction
HSTTAB==-1 ; include host table magic
HSTSIX==-1 ; and alias name kludge
.INSRT NETWRK[NET,MRC]
END SUPSER